package com.hzit.pay.web.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hzit.pay.web.factory.PayStrategyFactory;
import com.hzit.pay.web.iClient.IAliapyFrontClient;
import com.hzit.pay.web.model.MchInfo;
import com.hzit.pay.web.model.MchPayWay;
import com.hzit.pay.web.model.PaySerial;
import com.hzit.pay.web.service.*;
import com.hzit.pay.web.service.strategy.AliapyH5PayImpl;
import com.hzit.payweb.api.enums.PayStatusEnum;
import com.hzit.payweb.api.enums.PayWayEnum;
import com.hzit.payweb.api.req.PayReq;
import com.hzit.payweb.api.req.TradeQueryReq;
import com.hzit.payweb.api.resp.PayNotifyReq;
import com.hzit.payweb.api.resp.RespVo;
import com.hzit.payweb.api.resp.data.PayQueryRespData;
import com.hzit.payweb.api.resp.data.PayRespData;
import com.hzit.payweb.api.utils.PayDigestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * 支付业务接口实现类
 */
@Service
public class PayServiceImpl implements IPayService {

    private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);

    @Autowired
    private IMchInfoService mchInfoService;

    @Autowired
    private IMchPayWayService payWayService;

    @Autowired
    private IpaySerialService paySerialService;

    @Autowired
    private IAliapyFrontClient aliapyFrontClient;


    @Override
    public RespVo<PayRespData> createPay(PayReq payReq) {

        //2.判断mchid 是否存在商户表


        MchInfo mchInfo = mchInfoService.getMchInfoByMchId(payReq.getMchId());


        if (ObjectUtils.isEmpty(mchInfo) || "1".equals(mchInfo.getStatus())){
            logger.info("商户id：{}在数据库中没有找到记录，或状态不可用",payReq.getMchId());
            return RespVo.returnFail(-1,"没有商户找到记录，或状态不可用");
        }

        //3.判断商户是否支持该支付方式
        MchPayWay mchPayWay = payWayService.getMchPayWayByMchId(payReq.getMchId(),payReq.getPayWay());

        if(ObjectUtils.isEmpty(mchPayWay) || "1".equals(mchPayWay.getStatus())){
            logger.info("商户id：{},支付方式{}在数据库中没有找到记录，或状态不可用,",payReq.getMchId(),payReq.getPayWay());
            return RespVo.returnFail(-1,"没有商户找到此支付方式");
        }

        //4.验证签名。生成签名的时候要移除sign

        JSONObject jsonObject = (JSONObject)JSON.toJSON(payReq);
        String newSigin = PayDigestUtil.getSign(jsonObject,mchInfo.getReqKey(),"sign");

        if(!payReq.getSign().equals(newSigin)){
            logger.info("订单id：{}验证签名失败,请求sign：{},新生成的sign：{}",payReq.getOrderId(),payReq.getSign(),newSigin);
            return RespVo.returnFail(-1,"验证签名失败");
        }

        //5.生成支付流水
        PaySerial paySerial = null;
        try{

            //redis 分布锁上锁,
             paySerial = paySerialService.createPaySerial(payReq);

        }finally {

            //redis 释放锁
        }

        if (ObjectUtils.isEmpty(paySerial)){
            logger.info("订单id：{}：已经存在",payReq.getOrderId());
            return RespVo.returnFail(-1,"订单已经存在");
        }

        //策略模式 + 工厂模式

        //6.根据传过来payway调用对应的支付接口.
        IPayStrategyService iPayStrategyService = PayStrategyFactory.getPayStrategy(payReq.getPayWay());

        if(ObjectUtils.isEmpty(iPayStrategyService)){
            logger.info("没有找到订单id:{},所对应的支付方式:{}实现类",payReq.getOrderId(),payReq.getPayWay());
            return RespVo.returnFail(-1,"没有找到订单所对应的支付方式");
        }

        return iPayStrategyService.pay(paySerial);


    }

    @Override
    public RespVo<PayNotifyReq> queryTrade(TradeQueryReq queryReq) {
        //1.参数验证:空判断

        //2.验证签名 TODO

        //3.查询pay_serial
        PaySerial paySerial = paySerialService.queryTradingListByMchId(queryReq.getMchOrderNo(),queryReq.getMchOrderNo());
        if(ObjectUtils.isEmpty(paySerial)){
            return RespVo.returnFail(-1,"没有记录");
        }
        //4.状态如果是 支付中，就用 单笔查询口

        PayNotifyReq payNotifyReq = new PayNotifyReq();

        //2 和1 是需要调用接口确认状态
        if("2".equals(paySerial.getStatus()) || "1".equals(paySerial.getStatus())){

            RespVo<PayQueryRespData>  respVo = null ;
            //支付宝的
            if(paySerial.getPayWay().equals(PayWayEnum.ALIPAY_WAP_PAY.getCode())){
                //调用前支付的查询接口
                respVo = aliapyFrontClient.tradeSingleQuery(paySerial.getPaySerialNo(),paySerial.getBankRespNo().toString());

            } else if(paySerial.getPayWay().equals(PayWayEnum.WECHAT_QRCODE_PAY.getCode())){
                //调用微信接口 TODO
            }

            //接口调用失败
            if(respVo.getCode()!=0){
                logger.info("订单id：{}：调用前置服务返回失败：{}",queryReq.getMchOrderNo(),respVo);
                return RespVo.returnFail(-1,respVo.getMsg());
            }

            PayQueryRespData alipayQueryRespData  =  respVo.getData();

            String status = alipayQueryRespData.getTrade_status();
            String amout = alipayQueryRespData.getTotal_amount();

            //更新流水
            if(!paySerial.getPayAmt().equals(amout)){
                return RespVo.returnFail(-1,"金额不相等");
            } //等等


            if("TRADE_SUCCESS".equals(status) || "TRADE_FINISHED".equals(status)){
                //更新数据库记录为成功
                paySerialService.upDatePaySerial(paySerial.getPaySerialNo(), String.valueOf(PayStatusEnum.PAY_SUCCESS.getCode()));

                payNotifyReq.setPayStatus(String.valueOf(PayStatusEnum.PAY_SUCCESS.getCode()));
                payNotifyReq.setPaySuccessTime(paySerial.getPaySuccessTime().toString());
                payNotifyReq.setPayAmt(amout);
                //TODO

            }else if("TRADE_CLOSED".equals(status)){
                paySerialService.upDatePaySerial(paySerial.getPaySerialNo(), String.valueOf(PayStatusEnum.PAY_FAIL.getCode()));
                payNotifyReq.setPayStatus(String.valueOf(PayStatusEnum.PAY_FAIL.getCode()));
                payNotifyReq.setPayStatusDesc("TRADE_CLOSED,支付宝关闭交易");


            }else{
                payNotifyReq.setPayStatus(String.valueOf(PayStatusEnum.UNPAY.getCode()));
            }

            //生成签名

            payNotifyReq.setSign(""); //TODO

            RespVo sucRespVo = RespVo.returnSuccess("查询成功");
            sucRespVo.setData(payNotifyReq);
            return sucRespVo;

            //返回给还款服务
        }else {
            payNotifyReq.setSign(""); //TODO
            payNotifyReq.setPaySuccessTime(paySerial.getPaySuccessTime().toString());
            payNotifyReq.setPayStatus(paySerial.getStatus());
            //..... TODO

            RespVo respVo = RespVo.returnSuccess("查询成功");
            respVo.setData(payNotifyReq);
            return respVo;

        }
    }
}
